A Brief Discussion on .NET Default Logger and Optimization Techniques
TLDR
- .NET comes pre-integrated with Logger Providers such as Console, Debug, and EventSource.
- Through the
LogLevelsection inappsettings.json, you can configure granular log filtering for different namespaces or providers. - Use
logger.IsEnabled(LogLevel)to avoid performing expensive data operations when a log level is not enabled. - Prefer structured logging (using
{Placeholder}) over string concatenation to improve performance and facilitate analysis by systems like ELK. - If you need to display curly braces in logs, you must use double curly braces
for escaping. - It is recommended to use
AddJsonConsole()to output structured JSON for modern log management.
Default Logger Mechanism and Configuration
WebApplication.CreateBuilder() automatically loads default Logger Providers during initialization, including Console, Debug, and EventSource. Developers can customize this via builder.Logging, such as clearing default settings or adding specific providers.
When to use this: When the project needs to adjust the default log output destination (e.g., outputting only to Console) or requires full control over log sources.
// Example of adjusting LoggerProvider
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders(); // Clear default providers
builder.Logging.AddConsole(); // Add Console provider
builder.Logging.AddDebug(); // Add Debug providerControlling Log Levels via Appsettings.json
Through configuration files, you can set different log levels for specific namespaces or providers.
When to use this: When you need to hide excessive Debug information in a production environment while retaining Warning or Error records for specific services.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"LoggerTest.Services.TestService1": "Warning"
}
}
}- The outer
LogLevelapplies to all providers. - You can use the wildcard
*for batch configuration, such as"*.Services": "Warning".
Performance Optimization: Using Logger.IsEnabled
If generating a log involves expensive operations (such as database queries), you should check if the log level is enabled first.
When to use this: When log content requires fetching large amounts of data from a database or performing complex calculations, and the log level is typically disabled in production.
if (logger.IsEnabled(LogLevel.Information)) {
// Execute only when Information level is enabled to avoid performance waste
int processedRecords = await database.GetProcessedRecordsCount();
logger.LogInformation("System has finished data update, processed {Count} records.", processedRecords);
}Advantages and Implementation of Structured Logging
Structured logging avoids the performance overhead of string concatenation and separates parameters, making it easier for log analysis tools (like ELK) to index them.
When to use this: When you need to export logs to a centralized management system or want to improve application log processing performance under high load.
Correct Structured Writing
Avoid string concatenation; use placeholders instead:
// Recommended approach
logger.LogInformation("User {UserId} has logged into the system, Department: {Department}", user.Id, user.Department);Special Character Handling
If the log content itself contains curly braces, you must use double curly braces to escape them:
// The output will be: This is a JSON example: {"name": "value"}
logger.LogInformation("This is a JSON example: {{\"name\": \"value\"}}");Outputting JSON Format
Replace AddConsole() with AddJsonConsole() to output structured data directly:
builder.Logging.AddJsonConsole();Change Log
- 2025-03-23 Initial document creation.
